import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:mobile_app.core/core/presentation/utils/markdown_parser.dart';

Text buildMarkdown({
  required String markdown,
  required TextStyle textStyle,
  required TextAlign textAlign,
  required BuildContext context,
  double? textScaleFactor,
  TextWidthBasis? textWidthBasis,
  TextStyle? strongTextStyle,
  TextStyle? linkTextStyle,
  void Function({required String href})? onLinkPressed,
  TextStyle? markedTextStyle,
  TextStyle? emphasisedTextStyle,
}) {
  final nodes = parseMarkdown(markdown);

  final textSpans = <TextSpan>[];

  for (final node in nodes) {
    final nodeTextSpans = _buildNode(
      node: node,
      textStyle: textStyle,
      context: context,
      strongTextStyle: strongTextStyle,
      linkTextStyle: linkTextStyle,
      onLinkPressed: onLinkPressed,
      markedTextStyle: markedTextStyle,
      emphasisedTextStyle: emphasisedTextStyle,
    );

    textSpans.addAll(nodeTextSpans);
  }

  final textWidget = Text.rich(
    TextSpan(
      children: textSpans,
    ),
    textAlign: textAlign,
    textScaleFactor: textScaleFactor,
    textWidthBasis: textWidthBasis,
  );

  return textWidget;
}

List<TextSpan> _buildNode({
  required md.Node node,
  required TextStyle textStyle,
  required BuildContext context,
  TextStyle? strongTextStyle,
  TextStyle? linkTextStyle,
  void Function({required String href})? onLinkPressed,
  TextStyle? markedTextStyle,
  TextStyle? emphasisedTextStyle,
  void Function()? onPressed,
}) {
  switch (node) {
    case md.Text():
      GestureRecognizer? recognizer;

      if (onPressed != null) {
        recognizer = TapGestureRecognizer()..onTap = onPressed;
      }

      return [
        TextSpan(
          text: node.text,
          style: textStyle,
          recognizer: recognizer,
        ),
      ];

    case md.Element():
      var updatedTextStyle = textStyle;
      var updatedOnPressed = onPressed;

      switch (node.tag) {
        case 'strong':
          updatedTextStyle = textStyle.merge(strongTextStyle);

        case 'a':
          updatedTextStyle = textStyle.merge(linkTextStyle);

          final href = node.attributes['href'] as String;

          if (onLinkPressed != null) {
            updatedOnPressed = () {
              onLinkPressed(
                href: href,
              );
            };
          }

        case 'mark':
          updatedTextStyle = textStyle.merge(markedTextStyle);

        case 'em':
          updatedTextStyle = textStyle.merge(emphasisedTextStyle);
      }

      final textSpans = <TextSpan>[];

      for (final child in node.children!) {
        final childTextSpans = _buildNode(
          node: child,
          textStyle: updatedTextStyle,
          context: context,
          onLinkPressed: onLinkPressed,
          onPressed: updatedOnPressed,
          strongTextStyle: strongTextStyle,
          linkTextStyle: linkTextStyle,
          markedTextStyle: markedTextStyle,
          emphasisedTextStyle: emphasisedTextStyle,
        );

        textSpans.addAll(childTextSpans);
      }

      return textSpans;

    default:
      throw UnimplementedError();
  }
}
